package com.zdb.n1.service.impl;

import com.zdb.n1.entity.User;
import com.zdb.n1.payload.request.LoginRequest;
import com.zdb.n1.payload.request.RegisterRequest;
import com.zdb.n1.payload.request.UpdateUserRequest;
import com.zdb.n1.payload.request.AdminUpdateUserRequest;
import com.zdb.n1.payload.request.AdminCreateUserRequest;
import com.zdb.n1.payload.response.JwtResponse;
import com.zdb.n1.payload.response.MessageResponse;
import com.zdb.n1.payload.response.UserResponse;
import com.zdb.n1.repository.UserRepository;
import com.zdb.n1.security.JwtTokenUtil;
import com.zdb.n1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    public JwtResponse authenticateUser(LoginRequest loginRequest) {
        User user = userRepository.findByUsername(loginRequest.getUsername())
                .orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
        if (!user.isEnabled()) {
            throw new RuntimeException("账号已被禁用，请联系管理员");
        }
        String rawPassword = loginRequest.getPassword();
        String storedPassword = user.getPassword();
        boolean authenticated = false;
        if (storedPassword.startsWith("$2")) {
            authenticated = passwordEncoder.matches(rawPassword, storedPassword);
        } else {
            authenticated = rawPassword.equals(storedPassword);
            if (authenticated) {
                user.setPassword(passwordEncoder.encode(rawPassword));
                userRepository.save(user);
            }
        }
        if (!authenticated) {
            throw new BadCredentialsException("密码错误");
        }
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtTokenUtil.generateToken(user);
        return new JwtResponse(
                jwt,
                user.getId(),
                user.getUsername(),
                user.getEmail(),
                user.getAuthorities().stream().findFirst().get().getAuthority().substring(5)
        );
    }

    @Override
    @Transactional
    public MessageResponse registerUser(RegisterRequest registerRequest) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(registerRequest.getUsername())) {
            return MessageResponse.error("用户名已被使用");
        }

        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(registerRequest.getEmail())) {
            return MessageResponse.error("邮箱已被使用");
        }

        // 创建新用户
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setFullName(registerRequest.getFullName());
        user.setEmail(registerRequest.getEmail());
        user.setPhone(registerRequest.getPhone());
        user.setGender(registerRequest.getGender());
        user.setBirthDate(registerRequest.getBirthDate());
        user.setRegistrationDate(LocalDateTime.now());
        user.setEnabled(true);
        user.setRole(User.Role.USER);

        userRepository.save(user);

        return MessageResponse.success("用户注册成功");
    }

    @Override
    public User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("未找到当前用户"));
    }

    @Override
    public UserResponse getUserProfile(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("未找到用户"));
        return UserResponse.fromEntity(user);
    }

    @Override
    @Transactional
    public UserResponse updateUserProfile(UpdateUserRequest updateUserRequest) {
        User currentUser = getCurrentUser();
        if (updateUserRequest.getFullName() != null) {
            currentUser.setFullName(updateUserRequest.getFullName());
        }
        if (updateUserRequest.getEmail() != null && !updateUserRequest.getEmail().equals(currentUser.getEmail())) {
            if (userRepository.existsByEmail(updateUserRequest.getEmail())) {
                throw new RuntimeException("邮箱已被使用");
            }
            currentUser.setEmail(updateUserRequest.getEmail());
        }
        if (updateUserRequest.getPhone() != null) {
            currentUser.setPhone(updateUserRequest.getPhone());
        }
        if (updateUserRequest.getGender() != null) {
            currentUser.setGender(updateUserRequest.getGender());
        }
        if (updateUserRequest.getBirthDate() != null) {
            currentUser.setBirthDate(updateUserRequest.getBirthDate());
        }
        User updatedUser = userRepository.save(currentUser);
        return UserResponse.fromEntity(updatedUser);
    }

    @Override
    @Transactional
    public MessageResponse changePassword(String currentPassword, String newPassword) {
        User currentUser = getCurrentUser();
        if (!passwordEncoder.matches(currentPassword, currentUser.getPassword())) {
            return MessageResponse.error("当前密码不正确");
        }
        currentUser.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(currentUser);
        return MessageResponse.success("密码修改成功");
    }

    @Override
    public List<UserResponse> getAllUsers() {
        return userRepository.findAll().stream()
                .map(UserResponse::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public MessageResponse deleteUser(Long userId) {
        if (!userRepository.existsById(userId)) {
            return MessageResponse.error("用户不存在");
        }
        userRepository.deleteById(userId);
        return MessageResponse.success("用户删除成功");
    }

    @Override
    @Transactional
    public UserResponse adminUpdateUser(Long userId, AdminUpdateUserRequest adminUpdateUserRequest) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("未找到用户"));
        
        // 仅管理员可以更新其他用户
        User currentUser = getCurrentUser();
        if (!currentUser.getRole().equals(User.Role.ADMIN)) {
            throw new RuntimeException("无权限执行此操作");
        }
        
        // 不允许管理员修改其他管理员的信息
        if (user.getRole().equals(User.Role.ADMIN) && !user.getId().equals(currentUser.getId())) {
            throw new RuntimeException("不能修改其他管理员信息");
        }
        
        if (adminUpdateUserRequest.getFullName() != null) {
            user.setFullName(adminUpdateUserRequest.getFullName());
        }
        
        if (adminUpdateUserRequest.getEmail() != null && !adminUpdateUserRequest.getEmail().equals(user.getEmail())) {
            // 检查邮箱是否已被其他用户使用
            if (userRepository.existsByEmailAndIdNot(adminUpdateUserRequest.getEmail(), userId)) {
                throw new RuntimeException("邮箱已被使用");
            }
            user.setEmail(adminUpdateUserRequest.getEmail());
        }
        
        if (adminUpdateUserRequest.getPhone() != null) {
            user.setPhone(adminUpdateUserRequest.getPhone());
        }
        
        if (adminUpdateUserRequest.getGender() != null) {
            user.setGender(adminUpdateUserRequest.getGender());
        }
        
        if (adminUpdateUserRequest.getBirthDate() != null) {
            user.setBirthDate(adminUpdateUserRequest.getBirthDate());
        }
        
        // 更新启用状态
        if (adminUpdateUserRequest.getEnabled() != null) {
            user.setEnabled(adminUpdateUserRequest.getEnabled());
        }
        
        User updatedUser = userRepository.save(user);
        return UserResponse.fromEntity(updatedUser);
    }

    @Override
    @Transactional
    public UserResponse adminCreateUser(AdminCreateUserRequest request) {
        // 检查当前用户是否为管理员
        User currentUser = getCurrentUser();
        if (!currentUser.getRole().equals(User.Role.ADMIN)) {
            throw new RuntimeException("无权限执行此操作");
        }
        
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new RuntimeException("用户名已被使用");
        }

        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(request.getEmail())) {
            throw new RuntimeException("邮箱已被使用");
        }

        // 创建新用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setFullName(request.getFullName());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setGender(request.getGender());
        user.setBirthDate(request.getBirthDate());
        user.setRegistrationDate(LocalDateTime.now());
        user.setEnabled(request.isEnabled());
        user.setRole(request.getRole());

        User savedUser = userRepository.save(user);
        
        return UserResponse.fromEntity(savedUser);
    }

    @Override
    public User getUserById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("未找到用户"));
    }
} 